package com.xdf.ecommerce.filter;

import com.netflix.hystrix.strategy.HystrixPlugins;
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategyDefault;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier;
import com.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook;
import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher;
import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * Hystrix 请求缓存过滤器
 * @author chanchaw
 * @create 2025-10-30 13:55
 */
@Component
@Slf4j
@RequiredArgsConstructor
@WebFilter(
        filterName = "HystrixRequestContextServletFilter", // 过滤器名称，保证唯一
        urlPatterns = "/*", // 过滤器应用到的请求 uri
        asyncSupported = true) // 是否支持异步执行
public class HystrixRequestContextServletFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 初始化 hystrix 请求上下文，在不同的 context 中缓存是不共享的
        HystrixRequestContext context = HystrixRequestContext.initializeContext();
        try {
            hystrixConcurrencyStrategyConfig();// 配置并发策略
            filterChain.doFilter(servletRequest, servletResponse);
        } finally {
            context.shutdown();
        }
    }

    /**
     * hystrix 并发策略，当工程中存在 sleuth 依赖时，必须做该操作
     * 相反，如果没有使用 sleuth 则不需要本动作
     */
    public void hystrixConcurrencyStrategyConfig(){
        try {
            HystrixConcurrencyStrategy instance = HystrixConcurrencyStrategyDefault.getInstance();
            HystrixConcurrencyStrategy concurrencyStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy();
            if(concurrencyStrategy instanceof HystrixConcurrencyStrategyDefault) return;// 检查当前的策略已经是 HystrixConcurrencyStrategyDefault 则直接返回

            HystrixCommandExecutionHook commandExecutionHook = HystrixPlugins.getInstance().getCommandExecutionHook();
            HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance().getEventNotifier();
            HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance().getMetricsPublisher();
            HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance().getPropertiesStrategy();

            // 先重置，结合原来的配置写入自定义的配置
            HystrixPlugins.reset();
            HystrixPlugins.getInstance().registerConcurrencyStrategy(concurrencyStrategy);
            HystrixPlugins.getInstance().registerCommandExecutionHook(commandExecutionHook);
            HystrixPlugins.getInstance().registerEventNotifier(eventNotifier);
            HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher);
            HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy);
            log.info("Hystrix 为制作请求缓存配置并发策略完成");

        }catch(Exception ex){
            log.warn("制作Hystrix请求缓存前配置并发策略时出现异常：[{}]", ex.getMessage(), ex);
        }
    }
}
